package luke.audio.processing;

import luke.audio.metadata.Song;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 鼓点预处理类
 * 用于计算变速倍数和处理鼓点时间序列
 */
public class BeatPreprocessor {

    /**
     * 计算变速倍数
     *
     * @param originalBpm 原始BPM
     * @param targetBpm   目标BPM
     * @return 变速倍数
     */
    public static double calculateSpeedMultiplier(double originalBpm, double targetBpm) {
        // 计算初始倍数
        double multiplier = targetBpm / originalBpm;
        
        System.out.println("计算变速倍数: 目标BPM=" + targetBpm + ", 原始BPM=" + originalBpm + ", 倍数=" + multiplier);

        // 如果倍数大于等于1.8，不断除以2直到在合适的范围内
        if (multiplier >= 1.8) {
            while (multiplier >= 1.8) {
                multiplier /= 2.0;
            }
            System.out.println("调整后的倍数(>1.8): " + multiplier);
            return multiplier;
        }
        // 如果倍数小于等于0.2，不断乘以2直到在合适的范围内
        else if (multiplier <= 0.2) {
            while (multiplier <= 0.2) {
                multiplier *= 2.0;
            }
            System.out.println("调整后的倍数(<0.2): " + multiplier);
            return multiplier;
        }
        // 其他情况直接返回初始倍数
        else {
            System.out.println("直接使用的倍数: " + multiplier);
            return multiplier;
        }
    }

    /**
     * 对鼓点时间序列进行变速处理
     *
     * @param song            包含鼓点时间序列的歌曲对象
     * @param speedMultiplier 变速倍数
     * @return 变速后的鼓点时间序列
     */
    public static List<Integer> adjustBeatsForSpeed(Song song, double speedMultiplier) {
        List<Integer> originalBeats = new java.util.ArrayList<>();
        if (song.getBeatOffset() != 0) {
            originalBeats.add(song.getBeatOffset());
        }

        // 使用精确计算对每个鼓点时间进行变速处理
        return originalBeats.stream()
                .map(beatTime -> (int) Math.round(beatTime / speedMultiplier))
                .collect(Collectors.toList());
    }

    /**
     * 对鼓点偏移值进行变速处理
     *
     * @param beatOffset      包含鼓点偏移值（毫秒）
     * @param songDuration    歌曲时长（毫秒）
     * @param speedMultiplier 变速倍数
     * @return 变速后的鼓点偏移值
     */
    public static int adjustBeatOffsetForSpeed(int beatOffset, int songDuration, double speedMultiplier) {
        // 使用精确计算对偏移值进行变速处理
        int adjustedOffset = (int) Math.round(beatOffset / speedMultiplier);

        // 确保偏移值在合理范围内
        if (adjustedOffset < 0) {
            adjustedOffset = 0;
        }

        int adjustedSongDuration = (int) Math.round(songDuration / speedMultiplier);
        if (adjustedOffset > adjustedSongDuration) {
            adjustedOffset = adjustedSongDuration;
        }

        return adjustedOffset;
    }

}